﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Management;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using HAZ.ConnectionFactory;

namespace HAZ
{
    #region [ Criptografia ]
    public sealed class Cryption
    {
        UnicodeEncoding ByteConverter = new UnicodeEncoding();

        public Cryption()
        {
        }

        static public String Encrypt(String value)
        {
            try
            {
                /*
                MD5CryptoServiceProvider x = new MD5CryptoServiceProvider();
                byte[] data = System.Text.Encoding.ASCII.GetBytes(value);
                data = x.ComputeHash(data);
                return System.Text.Encoding.ASCII.GetString(data);
                //*/
                //*
                System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
                byte[] data = System.Text.Encoding.ASCII.GetBytes(value);
                data = x.ComputeHash(data);
                string ret = "";
                for (int i = 0; i < data.Length; i++)
                    ret += data[i].ToString("x2");
                
                return ret;
                //*/
            }
            //Catch and display a CryptographicException  
            //to the console.
            catch (CryptographicException e)
            {
                Console.WriteLine(e.Message);

                return null;
            }
        }
    }
    #endregion

    #region [ LICENÇA ]
    [Serializable]
    public sealed class License
    {
        public String   SerialKey  { get; set; }
        public String   Vendedor   { get; set; }
        public String   Obs        { get; set; }
        public DateTime DataCompra { get; set; }
        public DateTime DataVencto { get; set; }
        public String   LicenseKey { get; set; }

        public License() { }

        public void GenerateLicence()
        {
            string license = "";

            license += this.SerialKey;
            license += this.Vendedor;
            license += this.Obs;
            license += this.DataCompra.ToString();
            license += this.DataVencto.ToString();

            this.LicenseKey = Cryption.Encrypt(license);
        }

        public override string ToString()
        {
            StringBuilder sRet = new StringBuilder();
            sRet.AppendLine("Licença : "+this.LicenseKey);
            sRet.AppendLine("");
            sRet.AppendLine("Vendedor           "+this.Vendedor);
            sRet.AppendLine("Data da Compra     "+this.DataCompra.ToString("dd/MM/yyyy"));
            sRet.AppendLine("Data de Vencimento "+this.DataVencto.ToString("dd/MM/yyyy"));
            sRet.AppendLine("Obs : "+this.Obs);

            return sRet.ToString();
        }
    }
    #endregion

    #region [ SESSÃO ]
    public static class Session
    {
        private static string _serial = getSerialKey();

        public static String   Password 
        { get; set; }
        public static DateTime Start    
        {
            get; // Acesso externo somente lê a informação.
            // TODO: Inicializar quando SET PwdSession.
            private set;
        }
        public static String   Username 
        { get; private set; }
        public static String   Machine  
        { get; private set; }
        public static License  Licence  
        { get; private set; }
        public static String   Serial   
        {
            get
            {
                return _serial;
            }
        }
        public static DateTime DataAtual
        { get { return DateTime.Today; } }

        public static string getSerialKey()
        {
            try
            {
                string sret = "";
                ManagementObjectSearcher searcher;

                searcher = new ManagementObjectSearcher("SELECT * FROM Win32_ComputerSystemProduct");
                foreach (ManagementObject wmi in searcher.Get())
                {
                    sret += wmi.GetPropertyValue("Name").ToString();
                    sret += "-" + wmi.GetPropertyValue("UUID").ToString().Replace("0", "").Replace("-", "");
                }

                searcher = new ManagementObjectSearcher("SELECT * FROM Win32_Processor");
                foreach (ManagementObject wmi in searcher.Get())
                {
                    sret += "-" + wmi.GetPropertyValue("ProcessorId").ToString();
                }

                return sret;
            }
            catch { }

            return "Unknown";
        }
    }
    #endregion

    #region { (Enum)Databases Suportados ]
    /// <summary>
    /// ODBCs suportados pelo sistema, caso não haja um compativel
    /// , pode-se acessar via ODBC, caso suportado.
    /// </summary>
    public enum DBSuported
    {
        ODBC,
        OracleClient,
        SqlClient,
        SqlServerCE
    };
    #endregion

    #region [ Leitura de arquivos ]
    public partial class LoadFiles
    {
        public string Filename { get; set; }
        public LoadFiles(string filename)
        {
            this.Filename = filename;
        }

        public StringBuilder readFileWithTextMode()
        {
            StringBuilder strRet = null;

            try
            {
                strRet = new StringBuilder(new System.IO.StreamReader(this.Filename).ReadToEnd());
            }
            catch { throw; }

            return strRet;
        }
    }
    #endregion

    #region [ Serialização ]
    /// <summary>
    /// Helps with serializing an object to XML and back again.
    /// </summary>
    public static class Serialization
    {

        /// <summary>
        /// Serializes an object to binary
        /// </summary>
        /// <param name="Object">Object to serialize</param>
        /// <param name="Output">Binary output of the object</param>
        public static byte[] ObjectToBinary(object Object)
        {
            try
            {
                using (MemoryStream Stream = new MemoryStream())
                {
                    BinaryFormatter Formatter = new BinaryFormatter();
                    Formatter.Serialize(Stream, Object);
                    Stream.Seek(0, 0);
                    return Stream.ToArray();
                }
            }
            catch { throw; }
        }

        /// <summary>
        /// Deserializes an object from binary
        /// </summary>
        /// <typeparam name="T">Type of the object</typeparam>
        /// <param name="Binary">Binary representation of the object</param>
        /// <param name="Object">Object after it is deserialized</param>
        public static Object BinaryToObject<T>(byte[] Binary)
        {
            try
            {
                using (MemoryStream Stream = new MemoryStream())
                {
                    Stream.Write(Binary, 0, Binary.Length);
                    Stream.Seek(0, 0);
                    BinaryFormatter Formatter = new BinaryFormatter();
                    return (T)Formatter.Deserialize(Stream);
                }
            }
            catch { throw; }
        }
    }
    #endregion

    #region [ System Controls ]
    public class SysControls<T>
    {
        private static DBConnection dbConfig = DBConnection.Default;
        private static IDictionary _controles = LoadConfig();

        public static IDictionary LoadConfig()
        {
            return (IDictionary)dbConfig.Controles;
        }

        public static string AddControl(string sKey, object control)
        {
            if (!_controles.Contains(sKey))
            {
                _controles.Add(sKey, control);
                return "Objeto adicionado com sucesso.\r\nNão esqueça de salvar as configurações";
            }

            return "Chave de objeto já existe nas configurações.";
        }
        public static string RemoveControl(string sKey, object control)
        {
            if (_controles.Contains(sKey))
            {
                _controles.Remove(sKey);
                return "Objeto removido com sucesso.\r\nNão esqueça de salvar as configurações";
            }

            return "Chave de objeto não existe nas configurações.";
        }

        public static T GetControl(string sKey)
        {
            object oRet = null;

            if (_controles.Contains(sKey))
                return (T)_controles[sKey];
            
            return (T)oRet;
        }

        public static void SaveControls()
        {
            dbConfig.Controles = _controles;
            dbConfig.Save();
        }

        public static void ResetControls()
        {
            _controles = LoadConfig();
        }
    }
    #endregion
}